package main

import (
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/internal/json"

	"io/ioutil"
	"jgt-sdk/oper"
	"jgt-sdk/push"
	"os"
	"os/signal"
	"path/filepath"
	"strings"
	"time"

	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/ddd"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/listen"

	cmgorepo "gogs.xiaoyuanjijiehao.com/antlinker/antcms/core/repo/mgorepo"

	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/core"

	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/app/ginsrv/api/api"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/app/ginsrv/api/ginsess"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/app/ginsrv/api/share"
	apisrv "gogs.xiaoyuanjijiehao.com/antlinker/antcms/app/ginsrv/api/srv"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/app/ginsrv/api/svc"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/app/ginsrv/srv"

	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/app/ginsrv/api/manager"

	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/ddd/cache/inmemcache"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/ddd/event/memevt"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/ddd/repo/mgorepo"

	"jgt-sdk/asapi"

	"github.com/google/gops/agent"
	"github.com/pkg/errors"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/debug"
	"gogs.xiaoyuanjijiehao.com/antlinker/antcms/log"
	yaml "gopkg.in/yaml.v2"
)

// Auth 认证中心配置
type Auth struct {
	Addr         string `json:"addr,omitempty" yaml:"addr,omitempty"`
	ClientID     string `json:"client_id,omitempty" yaml:"client_id,omitempty"`
	ClientSecret string `json:"client_secret,omitempty" yaml:"client_secret,omitempty"`
	Identify     string `json:"identify,omitempty" yaml:"identify,omitempty"`
}

// Config 配置信息
type Config struct {
	Gops       string                 `json:"gops,omitempty" yaml:"gops,omitempty" `              // gops监听端口
	Mode       string                 `json:"mode,omitempty" yaml:"mode,omitempty" `              // 启动模式
	HTTP       *srv.Option            `json:"http,omitempty" yaml:"http,omitempty"`               // http服务配置
	StoreMode  string                 `json:"store_mode,omitempty" yaml:"store_mode,omitempty"`   // 存储模式
	MgoDB      *mgorepo.MongodbConfig `json:"mgo,omitempty" yaml:"mgo,omitempty"`                 // mongo配置
	Session    *ginsess.Option        `json:"session,omitempty" yaml:"session,omitempty"`         // 运营平台会话配置
	Auth       *Auth                  `json:"auth,omitempty" yaml:"auth,omitempty"`               // 认证配置
	Cache      *Cache                 `json:"cache,omitempty" yaml:"cache,omitempty"`             // 缓存配置
	SvcSession *ginsess.Option        `json:"svc_session,omitempty" yaml:"svc_session,omitempty"` // 服务平台会话配置
}

// Cache 缓存配置
type Cache struct {
	Type  string `json:"type,omitempty"`
	Memin struct {
		Expiration      int `json:"expiration,omitempty"`       // 有效期 单位秒
		CleanupInterval int `json:"cleanup_interval,omitempty"` // 清理间隔 单位秒
	} `json:"memin,omitempty"`
}

func parseConfig(file string) (cfg *Config, err error) {
	data, err := ioutil.ReadFile(file)
	if err != nil {
		return nil, errors.Wrapf(err, "配置文件读取失败")
	}
	switch strings.ToLower(filepath.Ext(file)) {
	case ".yaml":
		cfg, err = parseConfigYaml(data)
	case ".json":
		cfg, err = parseConfigJSON(data)
	default:
		return nil, errors.Errorf("配置文件名后缀错误")
	}
	if err != nil {
		return
	}
	return
}

//解析配置
func parseConfigYaml(configdata []byte) (cfg *Config, err error) {
	cfg = new(Config)
	err = yaml.Unmarshal(configdata, cfg)
	if err != nil {
		return nil, errors.Wrapf(err, "配置文件解析失败")
	}
	return

}

//解析配置
func parseConfigJSON(configdata []byte) (cfg *Config, err error) {

	err = json.Unmarshal(configdata, cfg)
	if err != nil {
		return nil, errors.Wrapf(err, "配置文件解析失败")
	}
	return

}

// 初始化授权API
func initAuthAPI(cfg Config) {
	auth := cfg.Auth
	handler := asapi.InitAPI(&asapi.Config{
		ASURL:           auth.Addr,
		ClientID:        auth.ClientID,
		ClientSecret:    auth.ClientSecret,
		ServiceIdentify: auth.Identify,
	})
	oper.InitOper(handler)
	push.InitPush(handler)
}
func runSrv(cfg Config) error {
	if cfg.Mode == "prod" {
		debug.Mode = debug.ModeProd
	}
	log.InitLogrus()

	if err := agent.Listen(agent.Options{Addr: cfg.Gops}); err != nil {
		log.Fatal(err)
	}
	// 注册ddd缓存
	if cfg.Cache != nil {
		switch cfg.Cache.Type {
		case "memin":
			cache := inmemcache.NewDDDCacher(time.Duration(cfg.Cache.Memin.Expiration)*time.Second, time.Duration(cfg.Cache.Memin.CleanupInterval)*time.Second)
			ddd.RegCacher(cache)
		}
	}

	ddd.RegEventTrigger(memevt.NewEventTrigger())
	var domain core.CmsDomain
	switch cfg.StoreMode {
	case "mgo":
		if cfg.MgoDB != nil {

			opt := cmgorepo.CreOption()
			domain = core.Reg(opt)
			db := mgorepo.CreateMyMgoForCfg(*cfg.MgoDB)
			mgorepo.DomainInitDB(domain, db)
			ddd.SetContextForRepo(mgorepo.NewExecCtxForRepoHandler(domain))
			// 创建索引
			mgorepo.CreateAllIndex()
		}

	default:
		return errors.Errorf("不支持%s模式的存储.", cfg.StoreMode)
	}
	srvopt := cfg.HTTP
	if srvopt == nil {
		srvopt = &srv.Option{}
	}
	srvopt.Domain = domain
	initAuthAPI(cfg)
	srv := srv.CreateServer(*srvopt)
	// 初始化运营平台接口
	manager.Init(srv, *cfg.Session)
	// 初始化代理接口
	api.Init(srv)
	// 初始化分享接口
	share.Init(srv)
	// 初始化服务接口
	apisrv.Init(srv)
	// 初始化服务平台接口
	svc.Init(srv, *cfg.SvcSession)
	// 初始化外部监听
	listen.Init(domain)
	errch := make(chan error)
	go func() {
		if err := srv.Run(); err != nil {
			errch <- err
		}

	}()

	sigc := make(chan os.Signal, 1)
	signal.Notify(sigc, os.Interrupt, os.Kill)
	select {
	case <-sigc:
		log.Info("收到了退出程序信号,开始停止服务")
		srv.Shutdown()
	case err := <-errch:
		log.Errorf("启动失败:%v", err)

	}
	return nil
}
